# coding: utf-8

# Models
from models import *

# Settings
from settings import *

# Libs
import subprocess, os
from datetime import datetime
from PIL import Image
from utils import EXIF
import re


class superdict (dict):
    def __missing__ (self, key):
        return ""


def post_upload_callback (sender, **kwargs):
    """
    Receiver function called each time an upload has finished.
    print "Post Upload Callback"
    print "kwargs:", kwargs
    # You can use all attributes available with the FileObject
    # This is just an example ...
    print "Filesize:", kwargs['file'].filesize
    print "Orientation:", kwargs['file'].orientation
    print "Extension:", kwargs['file'].extension
    """
    try:
        file_ext = kwargs['file'].extension.lower()

        if file_ext in IMAGE_TYPES:
            save_imagedata(sender, kwargs['file'])
        elif file_ext in AUDIO_TYPES:
            save_audiodata(sender, kwargs['file'])
        elif file_ext in VIDEO_TYPES:
            save_videodata(sender, kwargs['file'])
        else:
            save_filedata(sender, kwargs['file'])
    except Exception, inst:
        print "___"
        # the exception instance
        print "ERROR: Exception in medman.functions.post_upload_callback(): ", type(inst)
        # arguments stored in .args
        print inst.args
        print inst
        print "___"


def get_data_object(file_path):
    file_data_object = ImageData.objects.filter(file_field=file_path)
    if file_data_object.count() == 0:
        file_data_object = AudioData.objects.filter(file_field=file_path)
        if file_data_object.count() == 0:
            file_data_object = VideoData.objects.filter(file_field=file_path)
    return file_data_object


def post_delete_callback(sender, **kwargs):
    try:
        file_path = os.path.join(kwargs['path'], kwargs['filename'])
        
        file_data_object.get_data_object(file_path)
        file_data_object.delete()
        
    except Exception, inst:
        print "___"
        # the exception instance
        print "ERROR: Exception in medman.functions.post_delete_callback(): ", type(inst)
        # arguments stored in .args
        print inst.args
        print inst
        print "___"


def save_filedata(sender, file_object, filedata=None):
    save = False
    if not filedata:
        filedata = FileData()
        save = True
    
    filedata.filename = file_object.filename
    filedata.size = os.path.getsize(file_object.path_full)
    filedata.create_date = datetime.now()
    
    filedata.user = sender.user
    
    filedata.file_field = file_object.path
    
    if save:
        filedata.save()


def save_imagedata(sender, file_object):
    
    # delete existing object
    file_data_object = ImageData.objects.filter(file_field=file_object)
    if file_data_object.count() == 1:
        file_data_object.delete()
    
    # create new ImageData
    imagedata = ImageData()
    
    save_filedata(sender, file_object, imagedata)
    
    file_open = open(file_object.path_full, 'rb')
    exif_data = superdict(EXIF.process_file(file_open))
    
    im = Image.open(file_object.path_full);
    
    ### by pil
    
    # 2-tuple (width, height)
    imagedata.width, imagedata.height = im.size
    
    ### by exif.py
    
    # dates
    if exif_data['EXIF DateTimeDigitized']:
        digitized = datetime.strptime(str(exif_data['EXIF DateTimeDigitized']), '%Y:%m:%d %H:%M:%S')
        imagedata.dateTimeDigitized = digitized
    
    if exif_data['EXIF DateTimeOriginal']:
        original = datetime.strptime(str(exif_data['EXIF DateTimeOriginal']), '%Y:%m:%d %H:%M:%S')
        imagedata.dateTimeOriginal = original
    
    imagedata.exifVersion = exif_data['EXIF ExifVersion']
    imagedata.exposureTime = exif_data['EXIF ExposureTime']
    imagedata.fNumber = exif_data['EXIF FNumber']
    imagedata.flash = exif_data['EXIF Flash']
    imagedata.focalLength = exif_data['EXIF FocalLength']
    imagedata.isoSpeedRatings = exif_data['EXIF ISOSpeedRatings']
    imagedata.apertureValue = exif_data['EXIF ApertureValue']
    imagedata.maxApertureValue = exif_data['EXIF MaxApertureValue']
    imagedata.exposureProgram = exif_data['EXIF ExposureProgram']
    imagedata.exposureMode = exif_data['EXIF ExposureMode'] or exif_data['Image ExposureMode']
    imagedata.shutterSpeedValue = exif_data['EXIF ShutterSpeedValue']
    #imagedata.meteringMode = exif_data['EXIF MeteringMode']
    imagedata.colorSpace = exif_data['EXIF ColorSpace']
    imagedata.compressedBitsPerPixel = exif_data['EXIF CompressedBitsPerPixel']
    imagedata.lightSource = exif_data['EXIF LightSource']
    imagedata.subSecTimeOriginal = exif_data['EXIF SubSecTimeOriginal']
    imagedata.subSecTimeDigitized = exif_data['EXIF SubSecTimeDigitized']
    imagedata.sensingMethod = exif_data['EXIF SensingMethod']
    imagedata.customRendered = exif_data['EXIF CustomRendered'] or exif_data['Image CustomRendered']
    imagedata.whiteBalance = exif_data['EXIF WhiteBalance'] or exif_data['Image WhiteBalance']
    imagedata.digitalZoomRatio = exif_data['EXIF DigitalZoomRatio']
    imagedata.sceneCaptureType = exif_data['EXIF SceneCaptureType'] or exif_data['Image SceneCaptureType']
    imagedata.subjectDistanceRange = exif_data['EXIF SubjectDistanceRange']
    imagedata.contrast = exif_data['EXIF Contrast'] or exif_data['Image Contrast']
    imagedata.saturation = exif_data['EXIF Saturation'] or exif_data['Image Saturation']
    imagedata.sharpness = exif_data['EXIF Sharpness'] or exif_data['Image Sharpness']
    
    # image (???)
    imagedata.exifOffset = exif_data['Image ExifOffset']
    imagedata.orientation = exif_data['Image Orientation']
    imagedata.resolutionUnit = exif_data['Image ResolutionUnit']
    imagedata.xResolution = exif_data['Image XResolution']
    imagedata.yResolution = exif_data['Image YResolution']
    imagedata.model = exif_data['Image Model']
    imagedata.make = exif_data['Image Make']
    imagedata.software = exif_data['Image Software']
    imagedata.YCbCrPositioning = exif_data['Image YCbCrPositioning']
    
    # gps
    imagedata.gpsLongitude = exif_data['GPS GPSLongitude']
    imagedata.gpsLongitudeRef = exif_data['GPS GPSLongitudeRef']
    imagedata.gpsLatitude = exif_data['GPS GPSLatitude']
    imagedata.gpsLatitudeRef = exif_data['GPS GPSLatitudeRef']
    imagedata.gpsImgDirection = exif_data['GPS GPSImgDirection']
    imagedata.gpsImgDirectionRef = exif_data['GPS GPSImgDirectionRef']
    imagedata.gpsTimeStamp = exif_data['GPS GPSTimeStamp']
    imagedata.save()


def save_audiodata(sender, file_object):
    # delete existing object
    file_data_object = AudioData.objects.filter(file_field=file_object)
    if file_data_object.count() == 1:
        file_data_object.delete()
    
    audiodata = AudioData()
    
    # save generic data of the file (like size and name)
    save_filedata(sender, file_object, audiodata)
    
    if file_object.filename.endswith('.mp3'):
        from mutagen.mp3 import EasyMP3
        
        audio = EasyMP3(file_object.path_full)
        
        audiodata.length = audio.info.length
        audiodata.bitrate = audio.info.bitrate
        
        audiodata.id3_artist = audio.get('artist')[0]
        audiodata.id3_album = audio.get('album')[0]
        audiodata.id3_track = audio.get('title')[0]
    
    audiodata.save()


def save_videodata(sender, file_object):
    # delete existing object
    file_data_object = VideoData.objects.filter(file_field=file_object)
    if file_data_object.count() == 1:
        file_data_object.delete()
    
    # create new VideoData
    videodata = VideoData()
    
    # save generic data of the file (like size and name)
    save_filedata(sender, file_object, videodata)
    
    command = "mplayer -vo null -ao null -frames 0 -identify " + file_object.path_full
    process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    os.waitpid(process.pid, 0)
    output = process.stdout.read().strip()
    
    videodata.width = re.search(r"^ID_VIDEO_WIDTH=(.*)$", output, re.M).group(1)
    videodata.height = re.search(r"^ID_VIDEO_HEIGHT=(.*)$", output, re.M).group(1)
    videodata.length = re.search(r"^ID_LENGTH=(.*)$", output, re.M).group(1)
    
    videodata.video_format = re.search(r"^ID_VIDEO_FORMAT=(.*)$", output, re.M).group(1)
    videodata.video_bitrate = re.search(r"^ID_VIDEO_BITRATE=(.*)$", output, re.M).group(1)
    videodata.fps = re.search(r"^ID_VIDEO_FPS=(.*)$", output, re.M).group(1)
    
    videodata.audio_format = re.search(r"^ID_AUDIO_FORMAT=(.*)$", output, re.M).group(1)
    videodata.audio_bitrate = re.search(r"^ID_AUDIO_BITRATE=(.*)$", output, re.M).group(1)
    
    videodata.save()
